package cn.lili.modules.permission.serviceimpl;

import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.token.Token;
import cn.lili.common.utils.BeanUtil;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dos.Partner;
import cn.lili.modules.member.service.MemberService;
import cn.lili.modules.member.service.PartnerService;
import cn.lili.modules.permission.entity.dos.*;
import cn.lili.modules.permission.entity.dto.AdminUserDTO;
import cn.lili.modules.permission.entity.vo.AdminUserVO;
import cn.lili.modules.permission.entity.vo.AgentVO;
import cn.lili.modules.permission.mapper.AdminUserMapper;
import cn.lili.modules.permission.mapper.RoleMapper;
import cn.lili.modules.permission.service.*;
import cn.lili.modules.store.entity.dos.Store;
import cn.lili.modules.store.entity.vos.StoreVO;
import cn.lili.modules.store.mapper.StoreMapper;
import cn.lili.modules.system.aspect.annotation.SystemLogPoint;
import cn.lili.modules.system.token.ManagerTokenGenerate;
import cn.lili.mybatis.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户业务层实现
 *
 * @author Chopper
 * @since 2020/11/17 3:46 下午
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser> implements AdminUserService {
	@Autowired
	private UserRoleService userRoleService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private DepartmentService departmentService;
	@Autowired
	private MenuService menuService;
	@Autowired
	private ManagerTokenGenerate managerTokenGenerate;

	@Autowired
	private StoreMapper storeMapper;
	@Autowired
	private MemberService memberService;

	@Autowired
	private PartnerService partnerService;

	@Autowired
	private RoleMapper roleMapper;

	/**
	 * 角色长度
	 */
	private int rolesMaxSize = 10;

	@Override
	public IPage<AdminUserVO> adminUserPage(Page initPage, QueryWrapper<AdminUser> initWrapper) {
		// 获取当前角色下级所有的角色所分配的用户
		AuthUser currentUser = UserContext.getCurrentUser();
		AdminUser byId = this.baseMapper.selectById(currentUser.getId());
		List listIn = new ArrayList<>();
		if (byId.getIsSuper() == false) {
			// 不是超级管理员则获取当用户分配的前角色以和以下的角色
			List<Role> list = roleMapper.ListRole(byId.getRoleIds(), "0"); // 0平台 1商家
			list.forEach(item -> {
				listIn.add(item.getId());
			});
			initWrapper.in("role_ids", listIn);
		}
		Page<AdminUser> adminUserPage = page(initPage, initWrapper);
		List<Role> roles = roleService.list();
		List<Department> departments = departmentService.list();

		List<AdminUserVO> result = new ArrayList<>();

		adminUserPage.getRecords().forEach(adminUser -> {
			AdminUserVO adminUserVO = new AdminUserVO(adminUser);
			if (!CharSequenceUtil.isEmpty(adminUser.getDepartmentId())) {
				try {
					adminUserVO.setDepartmentTitle(departments.stream()
							.filter(department -> department.getId().equals(adminUser.getDepartmentId()))
							.collect(Collectors.toList()).get(0).getTitle());
				} catch (Exception e) {
					log.error("填充部门信息异常", e);
				}
			}
			if (!StringUtils.isEmpty(adminUser.getRoleIds())) {
				try {
					List<String> memberRoles = Arrays.asList(adminUser.getRoleIds().split(","));
					adminUserVO.setRoles(roles.stream().filter(role -> memberRoles.contains(role.getId()))
							.collect(Collectors.toList()));
				} catch (Exception e) {
					log.error("填充部门信息异常", e);
				}
			}
			result.add(adminUserVO);
		});
		Page<AdminUserVO> pageResult = new Page(adminUserPage.getCurrent(), adminUserPage.getSize(),
				adminUserPage.getTotal());
		pageResult.setRecords(result);
		return pageResult;

	}

	@Autowired
	private void setManagerTokenGenerate(ManagerTokenGenerate managerTokenGenerate) {
		this.managerTokenGenerate = managerTokenGenerate;
	}

	@Override
	public Token login(String username, String password) {
		AdminUser adminUser = this.findByUsername(username);

		if (adminUser == null || !adminUser.getStatus()) {
			throw new ServiceException(ResultCode.USER_PASSWORD_ERROR);
		}
		if (!new BCryptPasswordEncoder().matches(password, adminUser.getPassword())) {
			throw new ServiceException(ResultCode.USER_PASSWORD_ERROR);
		}
		try {
			return managerTokenGenerate.createToken(username, false);
		} catch (Exception e) {
			log.error("管理员登录错误", e);
		}
		return null;

	}

	@Override
	public Token refreshToken(String refreshToken) {
		return managerTokenGenerate.refreshToken(refreshToken);
	}

	@Override
	public AdminUser findByUsername(String username) {

		AdminUser user = getOne(new LambdaQueryWrapper<AdminUser>().eq(AdminUser::getUsername, username));

		if (user == null) {
			return null;
		}
		AdminUserVO adminUserVO = new AdminUserVO(user);
		// 关联部门
		if (user.getDepartmentId() != null) {
			Department department = departmentService.getById(user.getDepartmentId());
			if (department != null) {
				adminUserVO.setDepartmentTitle(department.getTitle());
			}
		}
		List<Role> roleList = this.baseMapper.findRoleById(user.getId());
		if (null != roleList) {
			adminUserVO.setRoles(roleList);
		}
		adminUserVO.setMenus(menuService.findUserList(user.getId()));
		return user;
	}

	@Override
	public List<Role> findRoleById(String id) {
		return this.baseMapper.findRoleById(id);
	}

	@Override
	@SystemLogPoint(description = "修改管理员", customerLog = "'修改管理员:'+#adminUser.username")
	public boolean updateAdminUser(AdminUser adminUser, List<String> roles) {

		if (roles != null && roles.size() > 0) {

			if (roles.size() > rolesMaxSize) {
				throw new ServiceException(ResultCode.PERMISSION_BEYOND_TEN);
			}
			adminUser.setRoleIds(StringUtils.join(",", roles));

		} else {
			adminUser.setRoleIds("");
		}

		updateRole(adminUser.getId(), roles);
		this.updateById(adminUser);
		return true;
	}

	@Override
	@SystemLogPoint(description = "修改代理商的代理区域", customerLog = "'修改代理商的代理区域:'+#adminUser.username")
	public boolean updateAdminUserRegion(AdminUser adminUser) {
		Member member = memberService.getById(adminUser.getId());
		member.setRegion(adminUser.getRegion());
		member.setRegionId(adminUser.getRegionId());
		memberService.updateById(member);

		QueryWrapper queryWrapper = new QueryWrapper();
		queryWrapper.eq("mobile", member.getMobile());
		AdminUser one = this.getOne(queryWrapper);
		if (null != one) {
			adminUser.setId(one.getId());
			this.updateById(adminUser);
		}
		QueryWrapper queryWrapper1 = new QueryWrapper();
		queryWrapper1.eq("member_id", member.getId());
		queryWrapper1.eq("partner_type", 4);
		queryWrapper1.eq("delete_flag", false);
		queryWrapper1.eq("partner_state", 0);
		Partner partner = partnerService.getOne(queryWrapper1);
		if (null != partner) {
			partner.setRegion(adminUser.getRegion());
			partner.setRegionId(adminUser.getRegionId());
			partnerService.updateById(partner);
		}
		return true;
	}

	@Override
	public void editPassword(String password, String newPassword) {
		AuthUser tokenUser = UserContext.getCurrentUser();
		AdminUser user = this.getById(tokenUser.getId());
		if (!new BCryptPasswordEncoder().matches(password, user.getPassword())) {
			throw new ServiceException(ResultCode.USER_OLD_PASSWORD_ERROR);
		}
		String newEncryptPass = new BCryptPasswordEncoder().encode(newPassword);
		user.setPassword(newEncryptPass);
		this.updateById(user);
	}

	@Override
	public void resetPassword(List<String> ids) {
		LambdaQueryWrapper<AdminUser> lambdaQueryWrapper = new LambdaQueryWrapper();
		lambdaQueryWrapper.in(AdminUser::getId, ids);
		List<AdminUser> adminUsers = this.list(lambdaQueryWrapper);
		String password = StringUtils.md5("123456");
		String newEncryptPass = new BCryptPasswordEncoder().encode(password);
		if (null != adminUsers && adminUsers.size() > 0) {
			adminUsers.forEach(item -> item.setPassword(newEncryptPass));
			this.updateBatchById(adminUsers);
		}
	}

	/**
	 * 根据手机号获取会员
	 *
	 * @param mobilePhone
	 *            手机号
	 * @return 会员
	 */
	@Override
	public AdminUser findByPhone(String mobilePhone) {
		QueryWrapper<AdminUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("mobile", mobilePhone);
		return this.baseMapper.selectOne(queryWrapper);
	}

	@Override
	public void saveAdminUser(AdminUserDTO adminUser, List<String> roles) {
		AdminUser dbUser = new AdminUser();
		BeanUtil.copyProperties(adminUser, dbUser);
		dbUser.setPassword(new BCryptPasswordEncoder().encode(dbUser.getPassword()));
		if (roles.size() > rolesMaxSize) {
			throw new ServiceException(ResultCode.PERMISSION_BEYOND_TEN);
		}
		if (!roles.isEmpty()) {
			dbUser.setRoleIds(CharSequenceUtil.join(",", roles));
		}
		this.save(dbUser);
		dbUser = this.findByUsername(dbUser.getUsername());
		updateRole(dbUser.getId(), roles);
	}

	@Override
	public void deleteCompletely(List<String> ids) {
		// 彻底删除超级管理员
		this.removeByIds(ids);

		// 删除管理员角色
		QueryWrapper<UserRole> queryWrapper = new QueryWrapper<>();
		queryWrapper.in("user_id", ids);
		userRoleService.remove(queryWrapper);
	}

	/**
	 * 更新用户角色
	 *
	 * @param userId
	 *            用户id
	 * @param roles
	 *            角色id集合
	 */
	@Override
	public void updateRole(String userId, List<String> roles) {

		QueryWrapper queryWrapper = new QueryWrapper();
		queryWrapper.eq("user_id", userId);
		userRoleService.remove(queryWrapper);

		if (roles == null || roles.isEmpty()) {
			return;
		}
		List<UserRole> userRoles = new ArrayList<>(roles.size());
		roles.forEach(id -> userRoles.add(new UserRole(userId, id)));
		userRoleService.updateUserRole(userId, userRoles);
	}

	@Override
	public IPage<AgentVO> getAgentPage(AgentVO agent, PageVO page) {
		QueryWrapper<AdminUser> queryWrapper = Wrappers.query();
		// 用户id查询
		queryWrapper.eq(CharSequenceUtil.isNotBlank(agent.getId()), "u.id", agent.getId());
		// 用户名查询
		queryWrapper.like(CharSequenceUtil.isNotBlank(agent.getUsername()), "u.username", agent.getUsername());
		// 用户名查询
		queryWrapper.like(CharSequenceUtil.isNotBlank(agent.getNickName()), "u.nick_name", agent.getNickName());
		// 按照电话号码查询
		queryWrapper.like(CharSequenceUtil.isNotBlank(agent.getMobile()), "u.mobile", agent.getMobile());
		// 只查询代理商
		// QueryWrapper<Role> wrapper = Wrappers.query();
		// wrapper.eq("name",UserEnums.AGENT.getRole());
		// Role role=roleService.getOne(wrapper);
		// queryWrapper.in("u.role_ids",role.getId());
		queryWrapper.eq("a.type", 1);
		queryWrapper.eq("a.delete_flag", false);
		queryWrapper.isNotNull("a.state");
		IPage<AgentVO> agentVOIPage = this.baseMapper.pageByAgentVO(PageUtil.initPage(page), queryWrapper);
		if (CollectionUtils.isNotEmpty(agentVOIPage.getRecords())) {
			for (AgentVO agentVO : agentVOIPage.getRecords()) {
				// 代理商推广的商家数量
				QueryWrapper<Store> storeQueryWrapper = Wrappers.query();
				storeQueryWrapper.eq("p.user_role", 1);
				storeQueryWrapper.eq("u.id", agentVO.getId());
				IPage<StoreVO> storeVOIPage = storeMapper.pageByStoreVO(PageUtil.initPage(page), storeQueryWrapper);
				agentVO.setAgentNum((int) storeVOIPage.getTotal());
				// 代理商佣金
				agentVO.setAgentMoney(BigDecimal.valueOf(0));
			}
		}
		return agentVOIPage;
	}

	@Override
	public Boolean updateStatus(String id, Boolean status) {
		UpdateWrapper<AdminUser> updateWrapper = Wrappers.update();
		updateWrapper.set("status", status);
		updateWrapper.eq("id", id);

		return this.update(updateWrapper);
	}
}
